package boxe.timer;

/**
 * Thread to decrease the timer
 * 
 */

import java.awt.Color;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import boxe.timer.env.Propertie;
import boxe.timer.manager.TimerController;
import boxe.timer.media.MediaTimer;

public class RunProcess implements Runnable { 
	
	private Mode mode;
	private TimerController timer;
	private List<Run> listRun;
	private MediaTimer media;
	private volatile Thread blinker;

	/**
	 *Constructor 
	 *	
	 * @param timer
	 * @param mode
	 */
	public RunProcess(TimerController timer, Mode mode) {
		this.timer = timer;
		this.mode = mode;
		listRun = new ArrayList<Run>();
		 media = new MediaTimer();
	}
	
    public void stop() {
        Thread tmpBlinker = blinker;
        blinker = null;
        if (tmpBlinker != null) {
           tmpBlinker.interrupt();
        }
    }

	
	/**
	 * Start thread for timer
	 * 
	 */
	public void run() {	 
		 int nbRun = 1;
		 long firstRun = 0;
		 List<Run> listRun = new ArrayList<Run>();
		 String modeName;

		 /*
		  * Loop throw the nb of rounds
		  */
			 while(nbRun <= mode.getNbRound()) {
				 /*
				  * init round
				  */
				 modeName = mode.getName();
				 listRun = createCurrentRound();
				 if(listRun != null && listRun.size() > 0 ) {
					firstRun = listRun.get(0).getDuration(); 
				 }
				 /*
				  * Loop throw the runs
				  */
				 for(Run run : listRun) {
					 /*
					  * init run
					  */
					 long duration = run.getDuration();
					 long current = 0;
					 long reftime = 0;
					 long now = 0;
					 long display = 0;
					 boolean isEndRun = run.isEndRun();
					 Color background = run.getBackground();
					 current = 0;
					 reftime = new Date().getTime() + Propertie.TIMER_OFFSET;
					 display = current; 
					 
					 //apply changes
					 timer.changeView(background, nbRun, duration);
					 timer.getWindow().setTxtTitle(modeName + " : " + run.getName());
					 playSound(run.getSndStart());
	
					 //Loop run
					 boolean endSoundRun = true;
					 
					 /*
					  * Loop throw the time of run
					  */
					 while(current < duration) {
						 now = new Date().getTime();
						 
						 //Stop
						 if (timer.isStop()) {
							 display = firstRun;
							 listRun.clear();
							 nbRun = mode.getNbRound() + 1;
							 break;
						 }
						 
						 //Start
						 else if (timer.isStart()) {
							 current = now - reftime;
							 display = duration - current;
							 if(display < 0) {
								 display = 0;
							 }
							 
							 //End run warning
							 if(isEndRun) {
								 if(display <= run.getEndRunWarning() + 1000){
									 background = run.getEndRunColor();
									 playSound(run.getSndEndRun());
									 isEndRun = false;
								 }
							 }
						 }
						 
						 //On hold
						 else if(timer.isHold()) {
							 reftime = now - current;
						 }
	
						 timer.changeView(background, nbRun, display);
						 if(endSoundRun &&display < 1000) {
							 playSound(run.getSndStop());
							 endSoundRun = false;
						 }
					     try {
					    	 Thread.sleep(Propertie.SLEEP);
					    	 
					     } catch (InterruptedException e) {
					    	 e.printStackTrace();
					  	 }    
					 }
				 }
			 //}
			 nbRun++; 
		 }
		 timer.stopTimer();
	}
	
	/**
	 * Play run's sound
	 * 
	 * @param run
	 */
	private void playSound(String sound) {
		 if(sound != null) {
			 media.playSound(sound);
		 }
	}

	/**
	 * Do a list of runs from the current round
	 * 
	 * @return
	 */
	private List<Run> createCurrentRound() {
		 listRun.clear();
		 for(RunPack runPack : mode.getListRunPack()){ 
			 String runName = runPack.getName();
			 for(Run run : runPack.getListRun()){
				 if(run.getDuration() > 0) {
					 run.setName(runName);
					 listRun.add(run);
				 }
			 }
		 }
		return listRun;
	}
}
